use tokio::{net::{TcpListener, TcpStream}};
use tracing::{info, debug, warn, error};
use std::io;

use kv::prelude::*;

async fn handle_client(client: TcpStream, service: Command)
{
    let mut msg = Conn::from(client);

    loop {
        let f = match msg.read().await {
            Ok(f) => {
                debug!("receive {:?}", f); 
                f
            },
            Err(e) => {warn!("{:?}", e); break;}
        };
        if let Some(result) = service.execute(f) {
            msg.write(result).await.unwrap();
        }
    }
    info!("Client disconnect");
}

#[tokio::main]
async fn main() -> io::Result<()> {
    tracing_subscriber::fmt::init();
    let storage = KvTable::new();
    let service = Command::new(storage);
    let listener = TcpListener::bind("0.0.0.0:955").await?;
    
    loop {
        match listener.accept().await {
            Ok((client, sockaddr)) => {
                let svc = service.clone();
                info!("Got connection from {:?}", sockaddr);
                tokio::spawn(handle_client(client, svc));
            },
            Err(_) => {error!("err");break;}
        }
    }

    Ok(())
}
